package com.fuyao.cloud.common.data.datascope;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.core.toolkit.PluginUtils;
import com.fuyao.cloud.common.security.service.CloudUser;
import com.fuyao.cloud.common.security.util.SecurityUtils;
import lombok.Setter;
import org.apache.ibatis.executor.Executor;
import org.apache.ibatis.mapping.BoundSql;
import org.apache.ibatis.mapping.MappedStatement;
import org.apache.ibatis.session.ResultHandler;
import org.apache.ibatis.session.RowBounds;

import java.util.List;
import java.util.Map;
import java.util.Optional;

/**
 * @author cloud
 * @date 2020/11/29
 */
public class DataScopeInnerInterceptor implements DataScopeInterceptor {

	@Setter
	private DataScopeHandle dataScopeHandle;


	@Override
	public void beforeQuery(Executor executor, MappedStatement ms, Object parameter, RowBounds rowBounds,
			ResultHandler resultHandler, BoundSql boundSql) {
		PluginUtils.MPBoundSql mpBs = PluginUtils.mpBoundSql(boundSql);

		String originalSql = boundSql.getSql();
		Object parameterObject = boundSql.getParameterObject();

		// 查找参数中包含DataScope类型的参数
		DataScope dataScope = findDataScopeObject(parameterObject);
		if (dataScope == null) {
			return;
		}

		String scopeName = dataScope.getScopeName();
		List<Long> deptIds = dataScope.getDeptIds();
		// 优先获取赋值数据
		if (CollUtil.isEmpty(deptIds) && dataScopeHandle.calcScope(deptIds)) {
			originalSql = String.format("SELECT %s FROM (%s) temp_data_scope", dataScope.getFunc().getType(),
					originalSql);
			mpBs.sql(originalSql);
			return;
		}

		// 当前权限用户
		if(dataScopeHandle.calcAuthorScope()){
			String selectField = dataScope.getSelect_field();
			CloudUser user = SecurityUtils.getUser();
			originalSql = String.format("SELECT %s FROM (%s) temp_data_scope where temp_data_scope.%s IN (%s) ", dataScope.getFunc().getType(),
					originalSql,selectField, StrUtil.builder().append("'").append(user.getUsername()).append("'").toString());
			mpBs.sql(originalSql);
			return;
		}

		//  判断是否为自定义配置权限选项。
		Integer menuDataScope = Optional.ofNullable(dataScope.getMenuDataScope()).orElse(0);
		if(dataScopeHandle.calcCustomizeItemScope()){
			// 数据权限为 all 直接返回
			if((DataScopeTypeEnum.ALL.getType()) == menuDataScope){
				return;
			}
            // 当前是自定义当前用户权限直接拼接SQL后返回
			if((DataScopeTypeEnum.OWN_AUTHOR.getType()) == menuDataScope){
                String selectField = dataScope.getSelect_field();
                CloudUser user = SecurityUtils.getUser();
                originalSql = String.format("SELECT %s FROM (%s) temp_data_scope where temp_data_scope.%s = %s ", dataScope.getFunc().getType(),
                        originalSql,selectField, StrUtil.builder().append("'").append(user.getUsername()).append("'"));
                mpBs.sql(originalSql);
                return;
			} else{
				// 自定义配置的本级或本级及下级则配置deptId。
				dataScopeHandle.splicingCustomizeDeptList(deptIds,menuDataScope);
			}
		}else{
			// 找其它角色的数据权限
			String scopeOther = dataScopeHandle.getCustomizeItemScopeOther();
			dataScopeHandle.splicingCustomizeOtherDeptList(deptIds,Integer.parseInt(scopeOther));
		}

        if (deptIds.isEmpty()) {
            originalSql = String.format("SELECT %s FROM (%s) temp_data_scope WHERE 1 = 2",
                    dataScope.getFunc().getType(), originalSql);
        } else {
            String join = CollectionUtil.join(deptIds, ",");
            originalSql = String.format("SELECT %s FROM (%s) temp_data_scope WHERE temp_data_scope.%s IN (%s)",
                    dataScope.getFunc().getType(), originalSql, scopeName, join);
        }

		mpBs.sql(originalSql);
	}

	/**
	 * 查找参数是否包括DataScope对象
	 * @param parameterObj 参数列表
	 * @return DataScope
	 */
	private DataScope findDataScopeObject(Object parameterObj) {
		if (parameterObj instanceof DataScope) {
			return (DataScope) parameterObj;
		}
		else if (parameterObj instanceof Map) {
			for (Object val : ((Map<?, ?>) parameterObj).values()) {
				if (val instanceof DataScope) {
					return (DataScope) val;
				}
			}
		}
		return null;
	}

}
